<?php
class system_controller_dispatcher {
	protected $_controllerDirectory;
	public function setControllerDirectory($controllerDirectory) {
		$this->_controllerDirectory = $controllerDirectory;
		return $this;
	}
	public function getControllerDirectory() {
		if(null === $this->_controllerDirectory) {			
			$this->setControllerDirectory('controller');
		}
		return _DIRECTORY_APP . DIRECTORY_SEPARATOR . $this->_controllerDirectory;
	}
	
	public function getBaseClassPre() {
		if(null === $this->_controllerDirectory) {
			$this->getControllerDirectory();
		}
		$controller = trim($this->_controllerDirectory, '/');
		return str_replace('/', '_', $controller) . '_';
	}
	
	public function getDefaultControllerName() {
		return 'index';
	}
	public function getDefaultActionName() {
		return 'index';
	}
	public function getControllerClass(system_controller_request_abstract $request) {
		$controllerName = $request->getControllerName();
		if(empty($controllerName)) {
			$controllerName = $this->getDefaultControllerName();
			$request->setControllerName($controllerName);
		}		
		return $this->getBaseClassPre() . strtolower($controllerName);
	}
	
	public function getActionMethod(system_controller_request_abstract $request) {
		$actionName = $request->getActionName();
		if(empty($actionName)) {
			$actionName = $this->getDefaultActionName();
			$request->setActionName($actionName);
		}
		return 'action_' . $actionName;
	}
	
	public function loadClass($className) {
		$loadFile = _DIRECTORY_APP . DIRECTORY_SEPARATOR . $this->classToFilename($className);
		if(file_exists($loadFile)) {
			return include_once $loadFile;
		} else {
			return false;
		}
	}
	
	public function dispatch(system_controller_request_abstract $request, system_controller_response_abstract $response) {
		$controllerClass = $this->getControllerClass($request);		
		if($this->loadClass($controllerClass)) {
			$controller = new $controllerClass($request, $response);			
			$action = $this->getActionMethod($request);
			ob_start();
			try {
				$controller->dispatch($action);
			} catch (Exception $e) {
				throw $e;
			}
			$content = ob_get_clean();
			$response->appendBody($content);
		} else {
			throw new Exception('Can not found the controller class :' . $controllerClass);
		}
	}
	
	public function classToFilename($class) {
		return str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
	}
}